package com.wlyuan.index.application.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.wlyuan.core.domain.valueobj.CombineId;
import com.wlyuan.core.exception.ValueError;
import com.wlyuan.index.api.ICombineIndexService;
import com.wlyuan.index.api.dto.QuotationIndexDTO;
import com.wlyuan.index.api.dto.combine.*;
import com.wlyuan.index.api.vo.CombineIndexScrollVO;
import com.wlyuan.index.api.vo.CombineIndexSumVO;
import com.wlyuan.index.api.vo.CombineIndexVO;
import com.wlyuan.index.application.translator.CombineIndexTranslator;
import com.wlyuan.index.domain.index.repository.CombineIndexRepository;
import com.wlyuan.index.domain.index.service.CombineIndexDiffService;
import com.wlyuan.index.domain.index.service.CombineIndexRenewService;
import com.wlyuan.index.domain.index.service.CombineIndexSearchService;
import com.wlyuan.index.domain.index.service.reindex.CombineReindexService;
import com.wlyuan.index.domain.source.factory.SourceFactory;
import com.wlyuan.index.domain.source.utils.SourceUtils;
import com.wlyuan.index.infrastructure.config.CombineIndexProperties;
import com.wlyuan.index.infrastructure.converter.CombineIndexConverter;
import com.wlyuan.tools.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import lombok.var;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @author yuanjie
 */
@DubboService
@Slf4j
@RequiredArgsConstructor
public class CombineIndexServiceImpl implements ICombineIndexService {
    private final CombineIndexProperties indexProperties;
    private final CombineIndexRepository indexRepository;
    private final CombineIndexRenewService renewService;
    private final CombineIndexDiffService diffService;
    private final CombineIndexSearchService searchService;
    private final CombineReindexService reindexService;
    private final SourceFactory sourceFactory;

    @Override
    public void index(Long combineId) {
        renewService.add(new CombineId(combineId));
    }

    @Override
    public void index(List<Long> combineIds) {
        if (CollectionUtils.isEmpty(combineIds)) {
            return;
        }
        combineIds.forEach(this::index);
    }

    @Override
    public void index(CombineIndexDTO combine) {
        if (logger.isDebugEnabled()) {
            logger.debug("合单信息更新: {}", JSON.toJSON(combine));
        }
        sourceFactory.create(combine);
        renewService.add(new CombineId(combine.getCombineId()));
    }

    @Override
    public void index(QuotationIndexDTO quotation) {
        if (logger.isDebugEnabled()) {
            logger.debug("报价信息更新: {}", JSON.toJSON(quotation));
        }
        if (!SourceUtils.isCombineQuote(quotation)) {
            logger.error("必须是合单报价: {}", quotation);
            return;
        }
        sourceFactory.create(quotation);
        renewService.add(new CombineId(quotation.getSourceId()));
    }

    @Override
    public Page<CombineIndexVO> search(CombineIndexFilterDTO filter) {
        return searchService.search(filter);
    }

    @Override
    public Page<CombineIndexVO> search(CombineIndexSearchDTO search) {
        return searchService.search(search);
    }

    @Override
    public CombineIndexScrollVO scroll(CombineIndexFilterDTO filter) {
        return CombineIndexTranslator.translate(searchService.scroll(filter));
    }

    @Override
    public CombineIndexScrollVO scroll(String scrollId) {
        return CombineIndexTranslator.translate(searchService.scroll(scrollId));
    }

    @Override
    public CombineIndexSumVO searchSum(CombineIndexFilterDTO filter) {
        return searchService.searchSum(filter);
    }

    @Override
    public void reindexAll(CombineReindexAllDTO reindex) {
        if (!indexProperties.isEnableReindexAll()) {
            logger.info("重建合单索引功能已禁用: {}", reindex);
            throw new ValueError("重建合单索引功能已禁用");
        }
        reindexService.reindexAll(reindex);
    }

    @Override
    public void reindexAll(List<Long> combineIds) {
        if (CollectionUtils.isEmpty(combineIds)) {
            return;
        }
        var ids = combineIds.stream()
                .map(CombineId::new)
                .collect(Collectors.toList());
        reindexService.reindexAll(ids);
    }

    @Override
    public void reindex(Long combineId) {
        reindexService.reindex(new CombineId(combineId));
    }

    @Override
    public void reindex(CombineReindexDTO reindex) {
        reindexService.reindex(reindex);
    }

    @Override
    public void remove(Long combineId) {
        indexRepository.deleteById(combineId);
    }

    @Override
    public CombineIndexVO getIndexById(Long combineId) {
        var index = indexRepository.ofId(new CombineId(combineId));
        return CombineIndexTranslator.translate(index);
    }

    @Override
    public JSONObject getCombineById(Long combineId) {
        return (JSONObject) JSON.toJSON(sourceFactory.getCombineById(new CombineId(combineId)));
    }

    @Override
    public JSONObject insight(Long combineId) {
        var indexCombineId = new CombineId(combineId);
        var source = sourceFactory.getSourceById(indexCombineId);
        var combine = sourceFactory.getCombineById(indexCombineId);
        var newIndex = CombineIndexConverter.convert(combine);
        source.put("newIndex", CombineIndexTranslator.translate(newIndex));
        source.put("oldIndex", this.getIndexById(combineId));
        return source;
    }

    @Override
    public JSONObject diffs() {
        var diffJson = new JSONObject();
        diffJson.put("diffs", JSON.toJSON(diffService.diffs()));
        diffJson.put("ignores", JSON.toJSON(diffService.ignores()));
        return diffJson;
    }
}
